#!/usr/bin/env python
# -*- coding: utf-8 -*-
# svn maven deploy project
#   by zkk@crscd.com.cn
# 约定：
#   仓库中，子目录均为头文件目录，单独头文件在根目录下，lib文件在目标目录下
# 
# install : install to local repo
# deploy  : deploy to svn, 默认xml
# export  : export to a local dir
# checkout: checkout to local repo
# fetch   : from SVN -> local repo -> local dir
#

from __future__ import unicode_literals, print_function

import sys, os
import logging
#import subprocess, shutil
#import lxml.etree as etree  # 使用该扩展xml库
import getopt
import imp      # use import utilities
#import importlib
#import types

from smvn import __version__
from smvn.config import *
from smvn.util import *
import smvn. template as tpl
from smvn.artifact import Artifact
from smvn.repo import Repo
from smvn.pom import Pom,XmlPom,XmlStrPom

# 保持一致
if sys.version_info.major == 2:
    input = raw_input

smvn_maps = {}

check_buildinfo()
drepo = config_parser()

def version_info():
    print('version: ' + __version__)

def usage():        
    prog = sys.argv[0].split('\\')[-1]
    usagestr = 'Usage: ' + prog +' [ <command> [OPTIONS] [FILES] ]'+ u"""
    rlist        cn/com/crscd 列出smvn仓库的子项 
    llist        cn/com/crscd 列出本地smvn目录的子项
    install [-Dversion=0.0.5] s.pom.xml 按照开发模式将本地文件复制到本地仓库 
    pinstall [-Dversion=0.0.5] s.pom.xml按照第三方的模块的方式安装
    deploy  [-Dversion=0.0.5] s.pom.xml 根据POM和定义从本地仓库发布到SVN目录 
    status  [-Dversion=0.0.5] s.pom.xml 类似于SVN status，检查本地仓库状态
    search  [-Dversion=0.0.5] s.pom.xml 搜索组件依赖的其他组件
    checkout [-Dversion=0.0.5] pom.xml  直接从SVN下载某个组件到本地目录
    rfetch pom.xml                      从SVN将组件取回到本地仓库
    fetch pom.xml                       将相关文件取回本地
    resolve pom.xml                     递归解析组件依赖性
    resolvep pom.xml                    解析本组件的依赖性
    arche:mkpom <dir>                   尝试构建pom.xml
    arche:tos <dir>                     将文件名变为短名字
    arche:tol <dir>                     将文件名变为长名字
"""
    print(usagestr)

class arg_map:
    def __init__(self):
        self.m = {'basepath': os.getcwd()}

    def __str__(self):
        return str(self.m)

    def flag_get(self, key):
        try:
            ret = self.m[key]
        except Exception, e:
            #print(e)
            ret = None
        return ret

    def flag_set(self, key, value):
        self.m[key] = value

    def flag_update(self, dst):
        for k, v in self.m.items():
            dst.flag_set(k, v)

def update_field(p, fmap, fs):
    for f in fs:
        v = fmap.flag_get(f)
        if v is not None:  setattr(p, f, v)

def get_xml(args):
    """
     get the first xml file of a argument list
    """
    if (len(args) >= 2 and args[1].endswith('.xml')):
        return args[1]
    else:
        # 17:09 
        return "pom.xml"

def update_pom_from_kb_input(args, p=None):
    id="app.example.example"
    ver="0.1.0"
    if len(args) == 0:
        print('>>>Welcome to pom creation wizard!')
        nid = input('>>>Please input your groupId and artifactId (%s) [Enter to accept]:'%id)
        nver = input('>>>Please input your version (%s) [Enter to accept]:'%ver)

        if nid != '' and '.' in nid:
            id = nid

        if nver != '':
            ver =nver
    else:
        if len(args) >= 1:
            id = args[0]
        if len(args) >= 2:
            ver = args[1]

    if p is None:
        p = XmlStrPom(tpl.pom_template)

    id_items = id.split('.')
    if len(id_items) <=1 :
        logging.error('Error version string!')
        sys.exit(-1)

    p.groupId = '.'.join(id_items[:-1])
    p.artifactId = id_items[-1]
    p.version = ver
    p.update_path()

    r = Repo(drepo)
    return p, r

def get_all_info(fmap, filename=""):
    repo = drepo
    p = XmlPom(filename)

    update_field(p, fmap, 
                 ['groupId', 'artifactId', 'version', 'compiler'])

    v = fmap.flag_get('repo')
    if v is not None:  repo = v

    if p.artifactId == "":
        logging.error("No avalable POM files found")
        sys.exit(-1)

    r = Repo(repo)

    return p, r

def core_call(func, fmap, args):
    try:
        func_name = func.strip()+'_handler'
        from smvn.plugins import core_smvn_plugin
        func = getattr(core_smvn_plugin, func_name)
        func(fmap, args)
    except AttributeError, e:
        print('Error plugin or command!', e)
        raise
        #sys.exit(-1)

def imp_call(mod, func, fmap, args):
    """
     use module name and function name to call a func, passing in fmap and args
    """
    try:
        func_name = func.strip()+'_handler'
        f = smvn_maps[mod][func_name] # global map
        f(fmap, args)
    except KeyError, e:
        print('Error plugin or command!', e)
        #sys.exit(-1)
        raise
    except AttributeError, e:
        print('Error plugin or command!', e)
        #sys.exit(-1)
        raise

def load_plugins(gmap, d):
    for p in d:
        mod_name = 'smvn.plugins.'+ p.strip()+'_smvn_plugin'
        m = __import__(mod_name, globals(), locals(), ["help_handler"])
        mod_funcs = {}
        for f in dir(m):
            if f.endswith("_handler"):
                mod_funcs[f] = getattr(m, f)
        gmap[p] = mod_funcs

    # add cm plugin to core list
    for k,v in gmap['cm'].items():
        if not gmap['core'].has_key(k):
            gmap['core'][k] = v

    # add arche plugin to core list
    for k,v in gmap['arche'].items():
        if not gmap['core'].has_key(k):
            gmap['core'][k] = v

def total_help(gmap):
    for v in gmap.values():
        if v.has_key('help_handler'):
            v['help_handler'](None, None)

def fmain(fmap, vlist):
    """
parse argv
"""
    #cmds = [cmd[0] for cmd in command_list]
    starti = 0
    command = ""
    if vlist[0][0] != '-':  # if vlist does not start with -
        command = vlist[0]
        starti = 1

    opts, args = getopt.getopt(
        vlist[starti:],
        "vD:o:w",
        [
            "help", "verbose", "version", "output:", "write",
        ]
    )

    if starti != 0:
        args.insert(0, command)

    if len(args) == 0 and len(opts) == 0:
        usage()
        sys.exit(2)

    for o, a in opts:
        if o in ('-h', '--help'):
            usage()
            sys.exit(2)
        elif o in ('-v', '--verbose'):
            fmap.flag_set('verbose', True)
            #logging.basicConfig(filename=default_dir+"/smvn.log", level=logging.INFO)
            #logging.basicConfig(format='[%(levelname)s] %(asctime)s %(message)s', level=logging.INFO)
            logging.basicConfig(format='[%(levelname)s] %(message)s', level=logging.DEBUG)
        elif o in ('-w', '--write'):
            fmap.flag_set('write', True)
        elif o in ('-o', '--output'):
            fmap.flag_set('output', a)
        elif o in ('-D'):
            temp = a.split('=')
            if (len(temp) > 1):
                fmap.flag_set(temp[0], temp[1])
                if not fmap.flag_get('__redefined'):
                    fmap.flag_set('__redefined', True)
            else:
                fmap.flag_set(temp[0], True)
        elif o in ('--version'):
            if not os.path.exists(default_dir):
                os.makedirs(default_dir)
            version_info()
            sys.exit(-1)

    if not fmap.flag_get('verbose'):
        logging.basicConfig(format='%(message)s', level=logging.INFO)

    load_plugins(smvn_maps, ['arche', 'cm', 'core'])

    if ':' in args[0]:
        m = args[0].split(':')
        imp_call(m[0], m[1], fmap, args)
    else:
        if args[0] == 'help':
            total_help(smvn_maps)
        else:
            imp_call('core', args[0], fmap, args)

def main():
    f = arg_map()
    if len(sys.argv) == 1:
        usage()
    else:
        fmain(f, sys.argv[1:])

if __name__ == '__main__':
    main()
